package bb.lanxing.manager;

import static android.content.Context.LOCATION_SERVICE;

import android.annotation.SuppressLint;
import android.location.GnssStatus;
import android.location.GpsStatus;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Build;
import android.os.Bundle;

import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

import bb.lanxing.App;
import bb.lanxing.calc.data.GpsPoint;
import bb.lanxing.calc.fixer.AltitudeCalibrator;
import bb.lanxing.common.config.Constants;
import bb.lanxing.common.engin.util.LocationRecorder;
import bb.lanxing.common.engin.util.LocationSimulator;
import bb.lanxing.util.CommonUtil;
import bb.lanxing.util.Log;

public class SystemLocationManager {
    private static final int GPS_TIME_INTERVAL_MAX = 5000;
    private static final int GPS_TIME_INTERVAL_MIN = 1000;
    private static final String TAG = "SystemLocationManager";
    private static volatile SystemLocationManager instance;
    private LocationManager locationManager;
    private Set<GpsChangedListener> mGpsChangedListenerSet;
    private boolean systemGpsWorked = false;
    private AltitudeCalibrator altitudeCalibrator = new AltitudeCalibrator();
    private boolean isLocSimulatorOpen = false;
    private LocationListener locationListener = new LocationListener() {
        @Override
        public void onLocationChanged(final Location location) {
            LocationRecorder.get().recordLocation(location);
            if (App.getContext().isDebugMode()) {
                Log.logd(TAG, "onLocationChanged location = " + location);
            }
            if (location == null || !CommonUtil.isPointValid(location)) {
                return;
            }
            if (location.getTime() < Constants.MIN_TIME_STAMP) {
                location.setTime(System.currentTimeMillis());
            }
            if (altitudeCalibrator != null) {
                altitudeCalibrator.process(location);
            }
            dispatchLocationChanged(new GpsPoint(location));
        }

        @Override
        public void onProviderDisabled(String provider) {
            Log.d(TAG, "onProviderDisabled provider = " + provider);
        }

        @Override
        public void onProviderEnabled(String provider) {
            Log.d(TAG, "onProviderEnabled provider = " + provider);
        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
            Log.d(TAG, "onStatusChanged provider = " + provider + ", status = " + status + ", extras = " + extras);
        }
    };

    public interface GpsChangedListener {
        void onGpsLocationChanged(GpsPoint gpsPoint);

        void onGpsStatusChanged(int event, GpsStatus status, GnssStatus gnssStatus);
    }

    private SystemLocationManager() {
        if (Build.VERSION.SDK_INT >= 24) {
            initGnssCallBack();
        } else {
            initGpsStatusListener();
        }
    }

    public static SystemLocationManager getInstance() {
        if (instance == null) {
            synchronized (SystemLocationManager.class) {
                if (instance == null) {
                    instance = new SystemLocationManager();
                }
            }
        }
        return instance;
    }

    public static void terminate() {
        if (instance != null) {
            instance.release();
            instance = null;
        }
    }

    private void release() {
        Log.logi(TAG, "release");
        systemGpsWorked = false;
        locationManager = null;
        locationListener = null;
        altitudeCalibrator = null;
        Set<GpsChangedListener> set = mGpsChangedListenerSet;
        if (set != null) {
            set.clear();
            mGpsChangedListenerSet = null;
        }
    }

    public void registerGpsChangedListener(GpsChangedListener listener) {
        if (mGpsChangedListenerSet == null) {
            mGpsChangedListenerSet = new HashSet();
        }
        mGpsChangedListenerSet.add(listener);
    }

    public void unregisterGpsChangedListener(GpsChangedListener listener) {
        Set<GpsChangedListener> set = mGpsChangedListenerSet;
        if (set != null) {
            set.remove(listener);
        }
    }

    public void dispatchLocationChanged(GpsPoint gpsPoint) {
        Set<GpsChangedListener> set = mGpsChangedListenerSet;
        if (set != null) {
            for (GpsChangedListener gpsChangedListener : set) {
                synchronized (mGpsChangedListenerSet) {
                    gpsChangedListener.onGpsLocationChanged(gpsPoint);
                }
            }
        }
    }

    @SuppressLint("MissingPermission")
    public boolean openSystemGps() throws IOException {
        if (systemGpsWorked) {
            return true;
        }
        if (isLocSimulatorOpen) {
            LocationSimulator.getInstance().registerLocationListener(locationListener);
        } else {
            if (locationManager == null) {
                try {
                    locationManager = (LocationManager) App.getContext().getSystemService(LOCATION_SERVICE);
                    if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
                        return false;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    return false;
                }
            }
            try {
                if (RemoteSharedPreference.getInstance().getBoolean(SPConstant.KEY_BATTERY_SAVING_MODE, false)) {
                    locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, GPS_TIME_INTERVAL_MAX, 0.0f, locationListener);
                } else {
                    int vInterval = GPS_TIME_INTERVAL_MIN;
                    if (App.getContext().isBatterySavingVersion()) {
                        vInterval = SharedManager.getInstance().getGpsLocationIntervalWithMP();
                    }
                    locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, vInterval, 0.0f, locationListener);
                }
                systemGpsWorked = true;
            } catch (Exception e2) {
                e2.printStackTrace();
                systemGpsWorked = false;
                return false;
            }
        }
        return true;
    }

    public void closeSystemGps() {
        if (LocationSimulator.isLocSimulatorOpen) {
            LocationSimulator.getInstance().unregisterLocationListener();
        } else {
            Log.logi(TAG, "closeSystemGps systemGpsWorked = " + systemGpsWorked + ", locationListener = " + locationListener);
            if (locationManager != null && locationListener != null) {
                locationManager.removeUpdates(locationListener);
            }
        }
        systemGpsWorked = false;
    }

    public boolean isSystemGpsWorked() {
        return systemGpsWorked;
    }

    public void updateAltitudeConfigs(int altitudeSource, int altitudeAdjustValue) {
        altitudeCalibrator.updateConfigs(altitudeSource, altitudeAdjustValue);
    }

    private void initGnssCallBack() {
        if (Build.VERSION.SDK_INT >= 24) {
        }
    }

    private void initGpsStatusListener() {
    }
}